<template>
  <div class="wrap container" ref="container">
    <!-- <div class="tabButton">
      <span class="chatButton">{{ $t('chatTab') }}</span>
      <span class="paintingButton" @click="$router.replace('/painting')">{{ $t('paintingTab') }}</span>
    </div> -->
    <div class="chat-container" :style="{ width: `calc(100vw - 20px)` }">
      <el-main class="chat-main">
        <div class="chat-messages" ref="chatMessages">
          <div v-for="(message, index) in messages" :key="index"
            :class="{ 'chat-message-left': message.role === 'assistant', 'chat-message-right': message.role === 'user' }">
            <div class="chat-avatar">
              <img v-show="message.role === 'assistant'" src="../assets/logo@2x.png" alt="">
            </div>
            <div class="chat-content">
              <span v-html="md.render(message.content)" class="chat-message-text"></span>
              <span
                v-show="message.role === 'assistant' && !inAnswer && message.content.includes(this.$t('chat.errorOccurred'))"
                class="regenerate">
                <el-icon class="Refresh" size="24">
                  <!-- <Refresh /> -->
                  <WarningFilled />
                </el-icon>
              </span>
            </div>
            <div class="chat-avatar">
              <img v-show="message.role === 'user'" src="../assets/avatar3.jpg" alt="">
            </div>
          </div>
          <div class="chat-message-left" v-show="loadingAnimation">
            <div class="chat-avatar">
              <img src="../assets/logo@2x.png" alt="">
            </div>
            <div class="chat-content">
              <!-- <span class="chat-message-text" style="height: 50px;line-height:50px;">{{ $t('chat.thinking') }} <el-icon
                  class="is-loading">
                  <Loading />
                </el-icon></span> -->
              <div class="loading-animation"><span></span></div>
            </div>
          </div>
          <div v-show="inAnswer" class="suspend" @click="suspend"><el-button type="danger" round>{{
            $t('chat.stopAnswering') }}</el-button></div>
        </div>
      </el-main>
      <!-- <el-icon class="voiceInput" @click="startRecognition" v-show="!Distinguish">
        <Microphone />
      </el-icon> -->
      <ball @click="startRecognition" v-show="!Distinguish"></ball>
      <!-- <MicrophoneAnimation  /> -->
      <!-- <el-input v-model="inputText" class="inputText" ref="inputText" v-show="Distinguish"></el-input> -->
      <!-- <el-icon class="voiceInput  is-loading" @click="endRecognition" v-show="Distinguish">
        <Loading />
      </el-icon> -->
      <Waveform ref="Waveform" />
    </div>

  </div>
  <pictureDialog ref="pictureDialog" :name="name" :loading="loading" :selectedImageIndex="selectedImageIndex"
    @DoubleClick="dialogVisible = false" :pictureList="pictureList" v-model="dialogVisible">
  </pictureDialog>
</template>

<script>
import MarkdownIt from 'markdown-it'
import Hljs from "highlight.js";  //高亮代码
import { parseTime, getuuid, speakText } from '../utils/index'
import pictureDialog from './components/pictureDialog.vue'
import Waveform from './components/Waveform.vue'; //声波效果
import ball from './components/ball.vue'; //声波效果
import MicrophoneAnimation from './components/MicrophoneAnimation.vue';
import "../assets/_highlight.js@11.8.0@highlight.js/styles/monokai-sublime.css";
export default {
  components: {
    pictureDialog,
    MicrophoneAnimation,
    Waveform,
    ball
  },
  data() {
    return {
      model: 'gpt-4o-all',
      messages: [],            // 聊天记录
      pictureList: [],         // 图片列表
      loadingAnimation: false, // 加载状态
      inAnswer: false,         // 回答中状态
      dialogVisible: false,     // 图片对话框状态
      isMicActive: false, // 控制麦克风是否激活
      stream: null,       // 保存音频流
      name: '',
      inputText: '',
      loading: false,
      isSpeak: true,
      Distinguish: false,
      recognition: null,
      answerContent: '',
      imageUrl: '',
      selectedImageIndex: '',
      controller: new AbortController(), // 创建AbortController实例
      signal: null,
      apiMessage: [
        { role: 'system', content: `你需要判断用户是想让你画图还是回答问题，如果是想让你画图你只需回答'#AA#'` }
      ],
      htmlStr: '',
      md: new MarkdownIt({
        html: true,
        typographer: true,
        highlight: function (str, lang) {
          if (lang && Hljs.getLanguage(lang)) {
            try {
              let idname = `name${getuuid()}`
              return `<pre class="hljs"><div class="code-block-header"><span class="code-block-header__lang">${lang}</span></div><code id='${idname}'>` +
                Hljs.highlight(lang, str, true).value +
                '</code></pre>';
            } catch (__) { }
          }
          return '';
        }
      })
    };
  },
  //生命周期 - 创建完成（访问当前this实例）
  created() {
    this.initRecognition()
    if (this.messages.length === 0) {
      this.messages.push(
        { created: parseTime(Date.now()), role: 'assistant', content: this.$t('chat.welcome'), Question: 'Hello' }
      )
    }
  },
  //生命周期 - 挂载完成（访问DOM元素）
  mounted() {
    // 监听点击事件
    this.$refs.container.addEventListener('click', this.handleClick);
    // 结束朗读
    // speechSynthesis.cancel()
    // 添加键盘事件监听器
    window.addEventListener('keydown', this.handleKeyDown);
    this.initWebSocket()
    // 定义全局点击处理函数
    window.handleImageClick = (index) => {
      this.selectedImageIndex = index; // 保存点击的索引
      this.dialogVisible = true;
    };
  },
  beforeDestroy() {
    // 清理监听点击事件
    this.$refs.container.removeEventListener('click', this.handleClick);
    if (this.recognition) {
      this.recognition.stop();  // 清理识别器
    }
    if (this.socket) {
      this.socket.close(); // 关闭 WebSocket 连接
    }
    window.removeEventListener('keydown', this.handleKeyDown);
  },
  methods: {
    // 处理点击事件,如果是a标签单独处理
    async handleClick(event) {
      if (event.target.tagName.toLowerCase() === 'a') {
        event.preventDefault();
        const requestBody = {
          Url: event.target.getAttribute('href'),
        };
        const response = await fetch('/api/open_chrome', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(requestBody),
          signal: this.controller.signal
        });
        if (!response.ok || !response.body) {
          throw new Error(`状态码：${response.status}`);
        }
        return
      }
    },
    suspend() {
      this.controller.abort();
      this.inAnswer = false
      this.loadingAnimation = false
    },
    async sendMessage(event) {
      if (this.inAnswer) {
        return
      }
      if (this.inputText === '') {
        return
      }
      if (event.shiftKey) {
        this.inputText += '\n'
      } else {
        // 执行发送信息的操作
        if (this.loading === true) {
          return false
        }
        let prompt = ''
        prompt = this.inputText
        const userMessage = { content: prompt, role: 'user', created: parseTime(Date.parse(new Date())) };
        this.messages.push(userMessage);
        this.inputText = ''
        // 发送信息后返回div底部
        this.$nextTick(() => {
          this.$refs.chatMessages.scrollTop = this.$refs.chatMessages.scrollHeight;
        })
        // 向后端发送请求，获取机器人的回复 GetGPTreply
        this.GetGPTreply(prompt)
      }
    },
    async GetGPTreply(prompt) {
      try {
        // 初始化状态和消息处理
        this.loadingAnimation = true;
        this.inAnswer = true;
        // 准备历史消息（优化深拷贝方式）
        const historyMessages = [...this.messages]
          .slice(-10) // 取最后10条
          .map(({ created, Question, ...keep }) => keep); // 解构删除不需要的字段
        // 构建请求体（优化对象结构）
        const requestBody = {
          model: this.model,
          messages: [...historyMessages, { role: 'user', content: prompt }],
          timeout: sessionStorage.getItem('AiTimeOut') * 1 || 15
        };
        // 创建新的请求控制器（优化取消逻辑）
        this.controller?.abort();
        this.controller = new AbortController();
        // 发送请求
        const response = await fetch('/ai/super_chat2', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(requestBody),
          signal: this.controller.signal
        });
        // 处理响应体不存在的情况
        if (!response.ok || !response.body) {
          throw new Error(`状态码：${response.status}`);
        }
        // 创建助理消息对象（统一消息创建逻辑）
        const createAssistantMessage = (content) => ({
          role: 'assistant',
          content: content,
          created: parseTime(Date.now()),
          Question: prompt
        });
        // 初始化消息流处理
        this.messages.push(createAssistantMessage(''));
        let buffer = '';
        const reader = response.body
          .pipeThrough(new TextDecoderStream())
          .getReader();
        // 处理流数据
        while (true) {
          const { value, done } = await reader.read();
          if (done) {
            // setTimeout(() => {
            // this.speak(this.messages[this.messages.length - 1].content)
            // }, 500);
            break
          };
          buffer += value;
          const lines = buffer.split(/\n/);
          buffer = lines.pop() || '';
          // 处理每条数据行
          for (const line of lines) {
            const trimmedLine = line.trim();
            if (!trimmedLine) continue;
            // 流式数据格式处理
            if (trimmedLine.startsWith('data: ')) {
              this.loadingAnimation = false;
              await this.processStreamData(trimmedLine.slice(6).trim());
            }
          }
        }
        // 处理非流式响应（图片结果）
        await this.processNonStreamData(buffer);
      } catch (error) {
        this.handleError(error);
      } finally {
        // 最终状态重置
        this.loadingAnimation = false;
        this.inAnswer = false;
        this.scrollToBottom();
      }
    },
    // 处理流式数据
    async processStreamData(jsonString) {
      try {
        const data = JSON.parse(jsonString);
        // 错误状态处理
        if (data.Status?.StatusCode && data.Status?.StatusCode > 0) {
          throw new Error(data.Status.Msg2Client);
        }
        // 正常回答处理
        if (data.answer) {
          const lastMsg = this.messages[this.messages.length - 1];
          lastMsg.content += data.answer;
          this.scrollToBottom();
        }
      } catch (e) {
        throw new Error(`${e.message}`);
      }
    },
    // 处理非流式数据
    async processNonStreamData(buffer) {
      if (!buffer) return;
      try {
        const result = JSON.parse(buffer);
        // 图片URL处理
        if (result.Data?.data?.[0]?.url) {
          const imageUrl = result.Data.data;
          const lastMsg = this.messages[this.messages.length - 1];
          this.pictureList = [...this.pictureList, ...imageUrl];
          const index = this.pictureList.length - 1
          this.selectedImageIndex = index
          lastMsg.content = `<pre><img src="${this.pictureList?.[index]?.url}" style="width: 520px" onclick="window.handleImageClick(${index})"/><p class="imgPrompt">${this.pictureList?.[index]?.revised_prompt}</p></pre>`;
          this.dialogVisible = true;
        } else {
          throw new Error(result.Data.Status.Msg2Client);
        }
      } catch (e) {
        throw new Error(`${e.message}`);
      }
    },
    // 错误处理
    handleError(error) {
      const errorMessage = error.message.includes('aborted')
        ? this.$t('chat.requestCanceled')
        : `${this.$t('chat.errorOccurred')}: ${error.message}`;
      if (this.messages.length > 0) {
        const lastMsg = this.messages[this.messages.length - 1];
        lastMsg.content = errorMessage;
      }
      this.scrollToBottom();
    },
    // 滚动到底部
    scrollToBottom() {
      this.$nextTick(() => {
        if (this.$refs.chatMessages) {
          this.$refs.chatMessages.scrollTop = this.$refs.chatMessages.scrollHeight;
        }
      });
    },
    speak(value) {
      this.isSpeak = false
      // 获取选中的文本
      const selection = window.getSelection().toString();
      speakText(selection || value)
    },
    Stopspeak() {
      this.isSpeak = true
      speechSynthesis.cancel()
    },
    initRecognition() {
      // 检查浏览器是否支持 Web Speech API
      if (!('webkitSpeechRecognition' in window)) {
        alert(`${this.$t('speechError.sorry')}`);
        return;
      }
      // 创建识别对象
      const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
      this.recognition = new SpeechRecognition();
      this.recognition.continuous = false; // 设置为 false 以进行一次语音识别
      this.recognition.interimResults = false; // 不需要中间结果
      // this.recognition.lang = 'zh-CN';
      // 处理开始
      this.recognition.onstart = (event) => {
        this.lastTranscript = '';
      };
      // 处理结束
      this.recognition.onend = (event) => {
        // this.recognition.start()
        this.Distinguish = false
      };
      // 处理结果
      this.recognition.onresult = (event) => {
        this.$refs.Waveform.stopRecording()
        const transcript = event.results[event.resultIndex][0].transcript.trim();

        // 一次识别，自动发送
        this.inputText += transcript; // 获取转化后的文本
        this.Distinguish = false
        this.sendMessage('$event')
        this.endRecognition()

        // 仅在识别结果和上次不同时才追加，避免重复
        if (transcript !== this.lastTranscript) {
          this.inputText += transcript;
          this.lastTranscript = transcript;
        }

      };
      // 处理错误
      this.recognition.onerror = (event) => {
        this.$refs.Waveform.stopRecording()
        this.Distinguish = false
        let content = ''
        console.log(event.error);
        switch (event.error) {
          case 'no-speech':
            content = `${this.$t('speechError.noSpeech')}`
            break;
          case 'network':
            content = `${this.$t('speechError.network')}`
            break;
          case 'not-allowed':
            content = `${this.$t('speechError.notAllowed')}`
            break;
          case 'audio-capture':
            content = `${this.$t('speechError.audioCapture')}`
            break;
          case 'language-not-supported':
            content = `${this.$t('speechError.languageNotSupported')}`
            break;
          case 'service-not-allowed':
            content = `${this.$t('speechError.serviceNotAllowed')}`
            break;
          case 'no-speech-input':
            content = `${this.$t('speechError.noSpeechInput')}`
            break;
          default:
            content = `${this.$t('speechError.error')}`
            break;
        }
        this.messages.push(
          { created: parseTime(Date.now()), role: 'assistant', content, Question: 'Hello' }
        )
        this.$refs.chatMessages.scrollTop = this.$refs.chatMessages.scrollHeight;
        console.error("识别错误:", event);
      };
    },
    // 开始语音识别
    async startRecognition() {
      if (this.isMicActive) {
        // 停止麦克风
        if (this.stream) {
          this.stream.getTracks().forEach(track => track.stop());
        }
        this.isMicActive = false;
      } else {
        // 启动麦克风
        try {
          this.stream = await navigator.mediaDevices.getUserMedia({ audio: true });
          this.isMicActive = true;
        } catch (error) {
          console.error('无法获取音频流:', error);
          // alert('无法访问麦克风，请检查权限设置。');
        }
      }
      this.inputText = ''
      // this.Stopspeak()
      if (!this.recognition) {
        this.initRecognition();  // 初始化识别器
      } else {
        this.recognition.start();
        this.Distinguish = true
        // this.$nextTick(() => {
        //   this.$refs.inputText.focus()
        // })
        this.$refs.Waveform.startRecording()
      }
    },
    // 结束语音试别
    endRecognition() {
      if (this.recognition) {
        this.Distinguish = false
        this.recognition.stop();
      }
      this.$refs.Waveform.stopRecording()
    },
    // 监听回车键
    handleKeyDown(event) {
      // alert(event.key)
      if (event.key === 'Enter') {
        event.preventDefault(); // 阻止默认行为
        if (this.dialogVisible) {
          this.dialogVisible = false
        } else if (this.Distinguish && this.inputText !== '') {
          this.sendMessage('$event')
          this.Distinguish = false
          this.recognition.stop();
        } else if (this.Distinguish && this.inputText === '') {
          this.Distinguish = false
          this.recognition.stop();
        } else {
          this.startRecognition(); // 切换识别状态
        }
      }
      // if (event.key === 'ArrowRight') {
      //   this.$router.replace('painting')
      // }
    },
    // 切换识别状态
    toggleRecognition() {
      if (this.Distinguish) {
        this.endRecognition();
      } else {
        this.startRecognition();
      }
    },
    getWebSocketUrl() {
      const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
      const host = window.location.hostname; // 获取当前域名或IP地址
      const port = window.location.port || (protocol === 'wss:' ? '443' : '80'); // 获取端口号，如果没有则使用默认端口
      return `${protocol}//${host}:${port}/ws`; // 拼接成完整的 WebSocket 地址
    },
    initWebSocket() {
      // 根据环境配置地址（生产环境使用wss）
      const isProduction = process.env.NODE_ENV === 'production'
      const wsUrl = isProduction
        ? this.getWebSocketUrl()
        : 'ws://192.168.20.88:20080/ws'
      this.ws = new WebSocket(wsUrl)
      this.ws.onopen = () => {
        console.log('WebSocket connected')
      }

      this.ws.onmessage = (e) => {
        try {
          const msg = JSON.parse(e.data)
          // 心跳处理（根据服务端实际结构）
          if (msg.Header?.CmdCode === 'Heartbeat') {
            this.sendPong()
            return
          }
          // 业务消息处理
          switch (msg.Header?.CmdCode) {
            case 'ControlInstruction':
              this.handleControlInstruction(msg.Data)
              break
            default:
              console.warn('未知消息类型:', msg)
          }
        } catch (error) {
          console.error('消息解析失败:', error)
        }
      }

      this.ws.onerror = (error) => {
        console.error('WebSocket error:', error)
      }

      this.ws.onclose = () => {
        console.log('WebSocket closed, reconnecting...')
        setTimeout(() => this.initWebSocket(), 3000) // 3秒重连
      }
    },


    handleControlInstruction(data) {
      const event = new KeyboardEvent('keydown', {
        bubbles: true,        // 事件是否冒泡
        cancelable: true,     // 事件是否可取消
        key: 'Enter',         // 按键名称
        code: 'Enter',        // 物理按键
        keyCode: 13,          // 回车键的 keyCode
        which: 13
      });
      switch (data.Inst) {
        case 1001: // 图片浏览上一张
          this.$refs['pictureDialog'].prev()
          this.endRecognition()
          break
        case 1002: // 图片浏览下一张
          this.$refs['pictureDialog'].next()
          this.endRecognition()
          break
        case 1003: // 退出图片预览
          this.handleKeyDown(event)
          this.endRecognition()
          break
        case 2001: // 开始语音识别
          if (this.dialogVisible === true) {
            this.dialogVisible = false
          }
          this.handleKeyDown(event)
          break
        case 2002: // 发送
          this.sendMessage('$event')
          break
        case 2003: // 清空(取消)
          this.inputText = ''
          this.endRecognition()
          break
        case 3001: // 朗读
          // this.speak(this.messages[this.messages.length - 1].content)
          this.endRecognition()
          break
        case 3002: // 取消朗读
          this.Stopspeak()
          this.endRecognition()
          break
        case 9001: // 中断回复
          this.suspend()
          this.endRecognition()
          break
        case 9002: // 发送文本问题
          if (this.dialogVisible === true) {
            this.dialogVisible = false
          }
          this.inputText = data.Question
          this.sendMessage('$event')
          this.endRecognition()
          break

        // ...其他指令处理
      }
    },

    sendPong() {
      const msg = {
        Header: { CmdCode: "ControlInstruction" },
        Data: { Response: "pong" }
      }
      this.ws.send(JSON.stringify(msg))
    },
  },
};
</script>

<style scoped lang="scss">
.wrap {
  position: relative;
  font-family: "Microsoft YaHei", Arial, sans-serif;
  display: flex;
  height: calc(100vh - 20px);
  background: #181c25;
  padding: 10px;

  :deep(.el-input__wrapper) {
    background: #283142 !important;
    box-shadow: 0 0 0 0px;
    border-radius: 0;

    .el-input__inner {
      color: #fff;
    }
  }

  .ArrowLeftBold {
    position: absolute;
    font-size: 20px;
    top: 45%;
    left: 270px;
    border-radius: 5px 0px 0px 5px;
    background: #459ffc;
    height: 30px;
    z-index: 100;
    cursor: pointer;

    svg {
      color: #fff;
    }
  }

  .tabButton {
    position: absolute;
    top: 20px;
    right: 20px;
    display: flex;
    background: #2a3346;
    color: #99a5be;
    z-index: 100;
    border-radius: 10px;
    cursor: pointer;

    .chatButton {
      background: #15ADB6;
      color: #fff;
      padding: 10px;
      border-radius: 10px;
    }

    .paintingButton {
      padding: 10px;
      border-radius: 10px;
    }
  }
}

.chat-container {
  position: relative;
  display: flex;
  flex-direction: column;
  background: #fff;
}

.chat-header {
  background-color: #409eff;
  color: white;
  text-align: center;
}


::-webkit-scrollbar {
  width: 5px;
}

/* 修改滚动条的轨道颜色 */
::-webkit-scrollbar-track {
  width: 5px;
  background-color: #2a3342;
}

/* 修改滚动条的滑块颜色 */
::-webkit-scrollbar-thumb {
  background-color: #4b586b;
}

/* 修改滚动条的滑块形状 */
::-webkit-scrollbar-thumb:hover {
  background-color: #6a7487;
}

/* 修改滚动条的角落 */
::-webkit-scrollbar-corner {
  background-color: #f1f1f1;
}

.sendInput {
  position: relative;
  padding: 20px;
  max-width: 80%;
  margin: 30px auto 0;

  .sendButton {
    position: absolute;
    bottom: 30px;
    right: 40px;
  }

  .cosplay {
    color: #b8b8b8;
    position: absolute;
    bottom: 8px;
    right: 50px;
    cursor: pointer;
  }

  .changeModel {
    position: absolute;
    left: 20px;
    top: -20px;
    color: #b8b8b8;
    position: absolute;
    bottom: 8px;
    right: 80px;
    cursor: pointer;
  }
}

.voiceInput {
  font-size: 50px;
  color: #009DFF;
  position: absolute;
  bottom: 40px;
  right: calc(50% - 20px);
  z-index: 100;
  cursor: pointer;
}

.chat-main {
  flex: 1;
  padding: 20px;
  background: #202735;
}

.chat-messages {
  height: calc(100vh - 180px);
  overflow-y: auto;
  font-size: 1rem;
  line-height: 25px;
  display: flex;
  flex-direction: column;

  .seeMore {
    text-align: center;
    cursor: pointer;
    color: #409EFF;
  }

  .regenerate {
    cursor: pointer;
    position: absolute;
    right: -20px;
    bottom: 8px;

    .el-icon svg {
      font-size: 28px !important;
      color: #F56C6C;
    }
  }

}



.suspend {
  position: relative;
  z-index: 10000;
  text-align: center !important;
  cursor: pointer;
  color: #F56C6C;
}

.chat-avatar {
  padding-top: 10px;

  img {
    width: 35px;
    border-radius: 50%;
  }
}

.chat-content {
  position: relative;
  display: flex;
  flex-direction: column;
}

pre {
  // background-color: #f4f6f8;
  padding: 10px;
  border-radius: 10px;
}

.chat-message-left {
  width: 80vw;
  display: flex;
  border-radius: 5px;
  margin: 10px 0;
  align-self: flex-start;

  .chat-message-text {
    width: 100%;
    overflow-y: auto;
    max-width: 80vw;
    align-self: flex-start;
    margin-left: 10px;
    border-radius: 5px;
    padding: 0 10px;
    color: #FEFEFF;
    // background-color: #283142;
    word-wrap: break-word;

    :deep(.imgPrompt) {
      white-space: normal !important;
      /* 默认值，确保文本换行 */
      word-wrap: break-word !important;
      /* 强制单词内换行（适用于长单词） */
      overflow-wrap: break-word !important;
      /* 现代浏览器支持，等同于 word-wrap */
      font-size: 1rem !important;
      cursor: pointer !important;
      font-family: "Microsoft YaHei", Arial, sans-serif !important;
    }
  }

  .chat-time {
    align-self: flex-start;
    font-size: 12px;
    color: #ccc;
    padding-left: 10px;
  }

  .copy {
    color: #409EFF;
    cursor: pointer;
  }
}

.chat-message-right {
  display: flex;
  max-width: 80%;
  border-radius: 5px;
  margin: 10px 0;
  align-self: flex-end;

  .chat-message-text {
    color: #fff;
    align-self: flex-end;
    margin-right: 10px;
    border-radius: 5px;
    padding: 0 10px;
    color: #FEFEFF;
    // background-color: #009dff;
  }

  .chat-time {
    font-size: 12px;
    color: #ccc;
    padding-right: 10px;
    align-self: flex-end;
  }
}


.chat-input {
  flex: 1;
  margin-right: 10px;
}

.chat-footer {
  position: fixed;
  bottom: 40px;
  width: 80%;
  left: 10%;
  display: flex;
  align-items: center;
}

.dialog-footer {
  display: inline-block;
  display: flex;
  align-items: right;
  justify-content: flex-end;
  padding-bottom: 40px;
  padding-right: 20px;
}

.day7::before {
  // content: "最近7天：" !important;
  color: #dddddd;
}

:focus {
  outline: 0;
}

// 加载动画
.loading-animation {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  margin: 20px;
}

.loading-animation::before,
.loading-animation::after,
.loading-animation span {
  content: '';
  width: 12px;
  height: 12px;
  background-color: #FEFEFF;
  border-radius: 50%;
  display: inline-block;
  animation: loading 1.2s infinite ease-in-out;
}

.loading-animation::before {
  animation-delay: -0.4s;
}

.loading-animation span {
  animation-delay: -0.2s;
}

.loading-animation::after {
  animation-delay: 0s;
}

@keyframes loading {

  0%,
  80%,
  100% {
    opacity: 0.3;
    transform: scale(0.8);
  }

  40% {
    opacity: 1;
    transform: scale(1.2);
  }
}
</style>

<style>
/** 列表样式 **/
table {
  border-collapse: collapse;
  width: 100%;
  margin: 1em 0;
  font-size: 16px;
}

th,
td {
  border: 1px solid #ddd;
  padding: 10px;
  text-align: left;
}

th {
  font-weight: 1000;
}

@media (max-width: 600px) {
  table {
    display: block;
    overflow-x: auto;
    white-space: nowrap;
  }
}


code {
  font-size: 1rem;
  font-family: '微软雅黑' !important;
}

html {
  font-size: 100%;
  /* 默认基准字体大小 */
}

body {
  font-size: 1rem;
  /* 16px */
}

@media (min-width: 1200px) {

  /* 针对大屏幕或投影仪 */
  .chat-messages {
    font-size: 2rem;
    /* 增大字体大小 */
  }
}

.markdown ol {
  list-style-type: decimal;
  padding-left: 40px;
}

.markdown ul {
  list-style-type: disc;
  padding-left: 40px;
}

.chat-content a {
  color: #5795e9;
  text-decoration: none;
  /* 可选：移除下划线 */
}

/* 设置图片宽度为 500px */
.chat-content img {
  width: 500px;
  height: auto;
  /* 保持纵横比 */
  display: block;
  /* 避免图片行内间距问题 */
}

.code-block-header {
  width: 100%;
  background: #000 !important;
  display: flex;
  justify-content: space-between;
  color: #dddddd;
}

.code-block-header__lang,
.code-block-header__copy {
  padding: 5px;
  cursor: pointer;
}

/* .demo-tabs{ */
.el-tabs__item {
  font-size: 14px;
  padding: 0 10px;
}

.el-tabs__nav:first-child::before {
  font-family: "Microsoft YaHei", Arial, sans-serif;
  font-size: 14px;
  padding-top: 10px;
  padding-left: 10px;
  padding-right: 10px;
  content: "模板：";
  color: #a3a3a3;
}

/* } */
</style>